package com.baosight.xCyber.util;

import com.baosight.xCyber.model.TagNode;
import com.baosight.xCyber.output.MapOutput;
import java.util.*;

/**
 * 解析数据库中数据获取字典输出至code.properties
 * @author 吴起航
 */
public class BuildCode {

    private CodeNode root =new CodeNode();

    public static Map<String,String> codeMap = new TreeMap<>();

    public class CodeNode {
        CodeNode preNode = null;    //获取父节点
        boolean isEnd;  //尾字符标识
        int deep = 0;       //做hash使用，当出现相同字符时，用于定位指定字符
        char content = 0;   //当前节点的字符
        boolean isCoincide=false; //树开始分叉的标识
        LinkedList<CodeNode> child = new LinkedList<>();//获取子节点

        CodeNode(){
        }
        CodeNode(char content) {
            this.isCoincide = true;
            this.content = content;
            this.isEnd = false;
        }

        public LinkedList<CodeNode> getChild() {
            return child;
        }

        public void setChild(LinkedList<CodeNode> child) {
            this.child = child;
        }

        void setPreNode(CodeNode node) {
            preNode = node;
        }

        CodeNode getPreNode() {
            return preNode;
        }

        /**
         * child中是否有此Node
         *
         * @param character 保存的char
         * @return 存在返回不存在返回Null
         */
        CodeNode getNode(Character character) {
            for (CodeNode aChild : child) {
                if (aChild.content == character) {
                    return aChild;
                }
            }
            return null;
        }
    }

    //map数据文件输出
    public static void outPutCode(Map<String,TagNode> nodeMap,String codePath) {
        BuildCode builderCode = new BuildCode();

        for(Map.Entry<String, TagNode> entry :nodeMap.entrySet()){
            TagNode tagNode = entry.getValue();
            //tagNameMap.put(tagNode.tagName,tagNode.showName);
            builderCode.initCode(tagNode.tagName);
        }

        //test:"src/main/resources/code.properties"
        MapOutput.writeProperties(codePath,codeMap);
    }

    /**
     * 根据字典树的算法，解析出code
     *
     * @param tagName 需要解析的节点名称
     */
    public void initCode(String tagName) {
        int deep = 0;
        String key;

        //初始化根节点
        CodeNode currNode = root;
        while (deep < tagName.length()) {
            /* 判断当前node的child，如果为空直接添加，不为空，
             * 查找是否含有，不含有则新建并设为currNode，含有则找到并设置为currNode
             */
            char c = tagName.charAt(deep);
            CodeNode node = currNode.getNode(c);
            //判断当前字符是否在其子节点字符中
            if (node != null) {
                //若是，则设置下次循环的主节点为当前字符
                //并设置当前节点分叉标识false
                node.isCoincide = false;
            } else {
                //若不是，则新建节点：设置当前节点分叉标识true，设置其父节点为根节点,并添加至根节点的子节点
                //深度+1
                //设置下次循环的主节点为当前字符
                node = new CodeNode(c);
                node.isCoincide = true;
                node.setPreNode(currNode);
                node.deep = deep + 1;
                currNode.child.add(node);
            }
            currNode = node;
            //判断当前字符是否已经遍历完毕
            if (deep == tagName.length() - 1) {
                while(node.isCoincide){
                    node = node.preNode;
                    deep--;
                }
                if(deep>0){
                    key = tagName.substring(0,deep+1);
                    if(!codeMap.containsKey(key)){
                        codeMap.put(key,key);
                    }
                }
                currNode.isEnd = true;
                break;
            }
            deep++;
        }
    }
}
